<?php namespace Phpcmf\Controllers\Admin;

class Home extends \Phpcmf\App
{

    private $phpfile = [];

    public function index() {

        $path = WRITEPATH.'backups/file/';
        $file = dr_dir_map($path, 1);
        if ($file) {
            $array = [];
            foreach ($file as $t) {
                if (is_file($path.$t.'/config.php')) {
                    $cfg = require $path.$t.'/config.php';
                    $files = $cfg['files'];
                } else {
                    $files = dr_lang('未知');
                }
                $array[] = [
                    'id' => $t,
                    'name' => dr_date($t, 'Y-m-d H:i:s'),
                    'files' => $files,
                ];
            }
            $file = $array;
        }

        $path = WRITEPATH.'backups/db/';
        $db = dr_dir_map($path, 1);
        if ($db) {
            $array = [];
            foreach ($db as $t) {
                if (is_file($path.$t.'/config.php')) {
                    $cfg = require $path.$t.'/config.php';
                    $files = dr_format_file_size($cfg['files']);
                } else {
                    $files = dr_lang('未知');
                }
                $array[] = [
                    'id' => $t,
                    'name' => dr_date($t, 'Y-m-d H:i:s'),
                    'files' => $files,
                ];
            }
            $db = $array;
        }

        \Phpcmf\Service::V()->assign([
            'menu' => \Phpcmf\Service::M('auth')->_admin_menu(
                [
                    '备份管理' => ['beifen/home/index', 'fa fa-copy'],
                ]
            ),
            'db' => $db,
            'file' => $file,
        ]);
        \Phpcmf\Service::V()->display('backup_index.html');
    }

    // 备份文件
    public function add() {

        \Phpcmf\Service::V()->assign([
            'check_url' => dr_url('beifen/home/file_check_index'),
            'count_url' => dr_url('beifen/home/file_count_index'),
        ]);
        \Phpcmf\Service::V()->display('backup_add.html');exit;
    }

    // 删除文件
    public function del() {

        $dir = dr_safe_filename($_GET['id']);
        !$dir && $this->_json(0, dr_lang('参数不存在'));

        $path = WRITEPATH.'backups/file/'.$dir.'/';
        !is_dir($path) && $this->_json(0, dr_lang('备份目录不存在'));

        dr_dir_delete($path, 1);
        is_dir($path) && $this->_json(0, dr_lang('删除失败，请手动删除'));

        $this->_json(1, dr_lang('操作成功'));
    }

    // 删除文件
    public function db_del() {

        $dir = dr_safe_filename($_GET['id']);
        !$dir && $this->_json(0, dr_lang('参数不存在'));

        $path = WRITEPATH.'backups/db/'.$dir.'/';
        !is_dir($path) && $this->_json(0, dr_lang('备份目录不存在'));

        dr_dir_delete($path, 1);
        is_dir($path) && $this->_json(0, dr_lang('删除失败，请手动删除'));

        $this->_json(1, dr_lang('操作成功'));
    }


    // php文件个数
    public function file_count_index() {

        // 读取文件到缓存
        foreach ([FCPATH, APPSPATH, TPLPATH, MYPATH, FCPATH, ROOTPATH] as $dir) {
            $this->_file_map($dir);
        }

        $cache = [];
        $count = $this->phpfile ? count($this->phpfile) : 0;
        if ($count > 100) {
            $pagesize = ceil($count/100);
            for ($i = 1; $i <= 100; $i ++) {
                $cache[$i] = array_slice($this->phpfile, ($i - 1) * $pagesize, $pagesize);
            }
        } else {
            for ($i = 1; $i <= $count; $i ++) {
                $cache[$i] = array_slice($this->phpfile, ($i - 1), 1);
            }
        }

        // 存储文件
        \Phpcmf\Service::L('cache')->set_data('backup-file', [
            'name' => SYS_TIME,
            'file' => $cache,
        ], 3600);

        $this->_json($cache ? count($cache) : 0, 'ok');
    }

    public function file_check_index() {

        $page = max(1, intval($_GET['page']));
        $cache = \Phpcmf\Service::L('cache')->get_data('backup-file');
        !$cache && $this->_json(0, dr_lang('数据缓存不存在'));
        !$cache['name'] && $this->_json(0, dr_lang('存储名称不存在'));

        $data = $cache['file'][$page];
        $backup = WRITEPATH.'backups/file/'.$cache['name'].'/';

        // 配置文件
        if (!is_file($backup.'config.php')) {
            $count = 0;
            foreach ($cache['file'] as $t) {
                $t && $count+= count($t);
            }
            file_put_contents($backup.'config.php', '<?php return [
            \'files\' => '.$count.',
        ];');
        }

        // 文件说明
        file_put_contents($backup.'备份目录说明.txt', 'FCPATH：'.FCPATH.PHP_EOL
            .'APPSPATH：'.APPSPATH.PHP_EOL
            .'TPLPATH：'.TPLPATH.PHP_EOL
            .'MYPATH：'.MYPATH.PHP_EOL
            .'ROOTPATH：'.ROOTPATH.PHP_EOL.PHP_EOL
        );

        if ($data) {
            $html = '';
            foreach ($data as $filename) {
                $fname = str_replace(
                    [FCPATH, APPSPATH, TPLPATH, MYPATH,  ROOTPATH],
                    ['FCPATH/', 'APPSPATH/', 'TPLPATH/', 'MYPATH/', 'ROOTPATH/'],
                    $filename
                );
                dr_mkdirs(dirname($backup.$fname));
                $rt = copy($filename, $backup.$fname);
                $class = '';
                if (!$rt) {
                    $ok = "<span class='error'>".dr_lang('失败')."</span>";
                    $class = ' p_error';
                } else {
                    $ok = "<span class='ok'>".dr_lang('完成')."</span>";
                }
                $html.= '<p class="'.$class.'"><label class="rleft">'.$fname.'</label><label class="rright">'.$ok.'</label></p>';
                $class && $this->_json(0, $html);
            }
            $this->_json($page + 1, $html);
        }

        \Phpcmf\Service::L('cache')->clear('backup-file');
        $this->_json(100, '');
    }

    // 遍历查询文件
    private function _file_map($source_dir) {
        if ($fp = @opendir($source_dir)) {
            $source_dir	= rtrim($source_dir, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR;
            while (false !== ($file = readdir($fp))) {
                // Remove '.', '..', and hidden files [optional]
                if (strpos($file, '.') === 0 || strpos($source_dir.$file, WRITEPATH) === 0) {
                    continue;
                }
                is_dir($source_dir.$file) && $file .= DIRECTORY_SEPARATOR;
                if (is_dir($source_dir.$file)) {
                    $this->_file_map($source_dir.$file);
                } else {
                    $this->phpfile[] = $source_dir.$file;
                }
            }
            closedir($fp);
        }
    }


    // 恢复数据库
    public function db_hf_add() {

        \Phpcmf\Service::V()->assign([
            'check_url' => dr_url('beifen/home/db_hf_check_index', [ 'id' => $_GET['id']]),
            'count_url' => dr_url('beifen/home/db_hf_count_index', [ 'id' => $_GET['id']]),
        ]);
        \Phpcmf\Service::V()->display('backup_add.html');exit;
    }

    // 恢复数据划分
    public function db_hf_count_index() {

        $backup = WRITEPATH.'backups/db/'.(int)$_GET['id'].'/';
        if (!is_file($backup.'table.sql')) {
            $this->_json(0, dr_lang('数据结构不存在'));
        }

        $cache = dr_save_bfb_data(dr_file_map($backup, 1));

        // 存储文件
        \Phpcmf\Service::L('cache')->set_data('backup-hfdb', [
            'name' => (int)$_GET['id'],
            'db' => $cache,
        ], 3600);

        $this->_json($cache ? count($cache) : 0, 'ok');
    }

    public function db_hf_check_index() {

        $id = (int)$_GET['id'];
        $page = max(1, intval($_GET['page']));
        $cache = \Phpcmf\Service::L('cache')->get_data('backup-hfdb');
        !$cache && $this->_json(0, dr_lang('数据缓存不存在'));
        !$cache['name'] && $this->_json(0, dr_lang('存储名称不存在'));
        $cache['name'] != $id && $this->_json(0, dr_lang('存储路径不一致'));

        $data = $cache['db'][$page];
        $backup = WRITEPATH.'backups/db/'.$cache['name'].'/';

        if ($data) {
            $html = '';
            if ($page == 1) {
                // 首次导入表结构
                $rt = \Phpcmf\Service::M('table')->_query(file_get_contents($backup.'table.sql'));
                !$rt['code'] && $this->_json(0, dr_lang('数据库结构导入失败：%s', $rt['msg']));
            }

            foreach ($data as $t) {

                if (in_array($t, ['config.php', 'table.sql'])) {
                    continue;
                }

                $rt = \Phpcmf\Service::M('table')->_query(file_get_contents($backup.$t));
                if ($rt['code']) {
                    $ok = "<span class='ok'>".dr_lang('完成')."</span>";
                    $class = '';
                    $name = $t;
                } else {
                    $ok = "<span class='error'>".dr_lang('失败')."</span>";
                    $class = ' p_error';
                    $name = $rt['msg'];
                }
                $html.= '<p class="'.$class.'"><label class="rleft">'.$name.'</label><label class="rright">'.$ok.'</label></p>';
                $class && $this->_json(0, $html);
            }
            $this->_json($page + 1, $html);
        }

        // 完成
        \Phpcmf\Service::L('cache')->clear('backup-hfdb');
        $this->_json(100, '');
    }


    // 备份数据库
    public function db_add() {

        \Phpcmf\Service::V()->assign([
            'check_url' => dr_url('beifen/home/db_check_index'),
            'count_url' => dr_url('beifen/home/db_count_index'),
        ]);
        \Phpcmf\Service::V()->display('backup_add.html');exit;
    }

    // 数据划分
    public function db_count_index() {

        $count = 0;
        $cache = [];
        $list = \Phpcmf\Service::M()->db->query('show table status')->getResultArray();
        foreach ($list as $t) {
            $cache[] = '0-'.$t['Name'].'-'.$t['Rows'];
            if ($t['Rows']) {
                $pz = 1000;
                if ($t['Rows'] > $pz) {
                    $nums = ceil($t['Rows']/$pz) + 1;
                    for ($i = 1; $i< $nums; $i++) {
                        $cache[] = $i.'1-'.$t['Name'].'-'.(($i-1)*$pz).'-'.$pz;
                    }
                } else {
                    $cache[] = '1-'.$t['Name'].'-0-'.$t['Rows'];
                }
            }
            $count+= $t['Data_length'];
        }

        $cache = dr_save_bfb_data($cache);

        // 存储文件
        \Phpcmf\Service::L('cache')->set_data('backup-db', [
            'name' => SYS_TIME,
            'db' => $cache,
            'count' => $count,
        ], 3600);

        $this->_json($cache ? count($cache) : 0, 'ok');
    }

    public function db_check_index() {

        $page = max(1, intval($_GET['page']));
        $cache = \Phpcmf\Service::L('cache')->get_data('backup-db');
        !$cache && $this->_json(0, dr_lang('数据缓存不存在'));
        !$cache['name'] && $this->_json(0, dr_lang('存储名称不存在'));

        $data = $cache['db'][$page];
        $backup = WRITEPATH.'backups/db/'.$cache['name'].'/';
        dr_mkdirs($backup);

        // 配置文件
        if (!is_file($backup.'config.php')) {
            file_put_contents($backup.'config.php', '<?php return [
            \'files\' => '.$cache['count'].',
        ];');
        }

        if ($data) {
            $html = '';
            foreach ($data as $t) {

                list($type, $table, $star, $end) = explode('-', $t);
                $fname = '【'.$table.'】';
                if ($type) {
                    // 数据
                    $fname.= dr_lang('数据：').$star.'-'.$end;
                    $rows = \Phpcmf\Service::M()->db->table($table)->limit($end, $star)->get()->getResultArray();
                    if ($rows) {
                        $sql = $this->_get_sql($table, $rows);
                        file_put_contents($backup.$table.'-'.$star.'-'.$end.'.sql', $sql);
                    }
                } else {
                    // 结构
                    $fname.= dr_lang('结构');
                    $sql = \Phpcmf\Service::M()->db->query("SHOW CREATE TABLE `".$table."`")->getRowArray();
                    $sql = 'DROP TABLE IF EXISTS `'.$table.'`;'.PHP_EOL.str_replace('CREATE TABLE', 'CREATE TABLE IF NOT EXISTS', $sql['Create Table']).';';
                    file_put_contents($backup.'table.sql', $sql.PHP_EOL.PHP_EOL, FILE_APPEND);
                }

                $class = '';
                $ok = "<span class='ok'>".dr_lang('完成')."</span>";
                $html.= '<p class="'.$class.'"><label class="rleft">'.$fname.'</label><label class="rright">'.$ok.'</label></p>';
                //$class && $this->_json(0, $html);
            }
            $this->_json($page + 1, $html);
        }

        // 当前的管理员数据
        $sql = $this->_get_sql(
            \Phpcmf\Service::M()->dbprefix('admin'),
            \Phpcmf\Service::M()->db->table('admin')->where('uid', $this->uid)->get()->getResultArray()
        );
        $sql.= $this->_get_sql(
            \Phpcmf\Service::M()->dbprefix('admin_role'),
            \Phpcmf\Service::M()->db->table('admin_role')->get()->getResultArray()
        );
        $sql.= $this->_get_sql(
            \Phpcmf\Service::M()->dbprefix('admin_role_index'),
            \Phpcmf\Service::M()->db->table('admin_role_index')->where('uid', $this->uid)->get()->getResultArray()
        );
        $sql.= $this->_get_sql(
            \Phpcmf\Service::M()->dbprefix('member'),
            \Phpcmf\Service::M()->db->table('member')->where('id', $this->uid)->get()->getResultArray()
        );
        $sql.= $this->_get_sql(
            \Phpcmf\Service::M()->dbprefix('member_data'),
            \Phpcmf\Service::M()->db->table('member_data')->where('id', $this->uid)->get()->getResultArray()
        );

        file_put_contents($backup.'table.sql', $sql.PHP_EOL.PHP_EOL, FILE_APPEND);

        // 完成
        \Phpcmf\Service::L('cache')->clear('backup-db');
        $this->_json(100, '');
    }

    // 获取数据插入的sql
    private function _get_sql($table, $rows) {

        if (!$rows) {
            return '';
        }

        $sql = '';
        foreach ($rows as $tt) {
            $sql1 = $sql2 = [];
            foreach($tt as $cname => $value) {
                $sql1[] = "`{$cname}`";
                $sql2[] = "'".addslashes($value)."'";
            }
            $sql.= "REPLACE INTO `{$table}` (".implode(',', $sql1).") VALUES (".implode(',', $sql2).");".PHP_EOL;
        }

        return $sql;
    }
}
